#ifndef MD5_H_
#define MD5_H_

#include "config.h"
#include <stdint.h>
#include <string>

BEGIN_NAMESPACE_TOXIC

using std::string;

class MD5 {
public:
	enum OpenMode {
		TEXT, BINARY
	};

public:
	MD5();
	MD5(const void* input, size_t length);
	MD5(const string& str);
	MD5(const char* filename, OpenMode mode);
	MD5(const string& filename, OpenMode mode);

	void update(const void* input, size_t length);
	void update(const string& str);
	void update(const char* filename, OpenMode mode);
	void update(const string& filename, OpenMode mode);

	void reset();
	const byte* digest();
	string toString();

private:
	void update(const byte* input, size_t length);
	void final();
	void transform(const byte block[64]);
	void encode(const uint32_t* input, byte* output, size_t length);
	void decode(const byte* input, uint32_t* output, size_t length);
	string bytesToHexString(const byte* input, size_t length);

private:
	static const byte PADDING[64];	/* padding for calculate */
	static const char HEX[16];		/* hex table for bytesToHexString */

private:
	uint32_t _state[4];	/* state (ABCD) */
	uint32_t _count[2];	/* number of bits, modulo 2^64 (low-order word first) */
	byte _buffer[64];	/* input buffer */
	byte _digest[16];	/* message digest */
	bool _finished;		/* calculate finished ? */
};

END_NAMESPACE_TOXIC

#endif /* MD5_H_ */
